<!--
 * @Descripttion: 数据表格组件
 * @version: 1.10
 * @Author: lygmanager
 * @Date: 2024年06月08日11:51:15
 * @LastEditors: lygmanager
 * @LastEditTime: 2024年06月08日11:51:15
-->

<template>
  <div class="lakerTable" :style="{ height: _height }" ref="lakerTableMain" v-loading="loading">
    <div class="lakerTable-table" :style="{ height: _table_height }">
      <el-table
        v-bind="$attrs"
        :data="tableData"
        :row-key="rowKey"
        :key="toggleIndex"
        ref="lakerTable"
        :height="height == 'auto' ? null : '100%'"
        :size="config.size"
        :border="config.border"
        :stripe="config.stripe"
        :summary-method="remoteSummary ? remoteSummaryMethod : summaryMethod"
        @sort-change="sortChange"
        @filter-change="filterChange"
        :row-class-name="rowClassName"
      >
        <el-table-column type="selection" width="40" align="center"></el-table-column>
        <el-table-column type="index" width="60" fixed="left" label="序号" :index="indexMethod" align="center">
        </el-table-column>
        <slot></slot>
        <template v-for="(item, index) in userColumn" :key="index">
          <el-table-column
            v-if="!item.hide"
            :column-key="item.prop"
            :label="item.label"
            :prop="item.prop"
            :width="item.width"
            :sortable="item.sortable"
            :fixed="item.fixed"
            :filters="item.filters"
            :filter-method="remoteFilter || !item.filters ? null : filterHandler"
            :show-overflow-tooltip="item.showOverflowTooltip"
            :formatter="item.formatter ? formatDict : null"
            :class-name="item.className"
            :align="item.align"
          >
            <template v-if="item.children">
              <template v-for="(item1, index1) in item.children" :key="index1">
                <el-table-column
                  v-if="!item1.hide"
                  :column-key="item1.prop"
                  :label="item1.label"
                  :prop="item1.prop"
                  :width="item1.width"
                  :sortable="item1.sortable"
                  :fixed="item1.fixed"
                  :filters="item1.filters"
                  :filter-method="remoteFilter || !item1.filters ? null : filterHandler"
                  :show-overflow-tooltip="item1.showOverflowTooltip"
                  :formatter="item1.formatter ? formatDict : null"
                  :class-name="item1.className"
                  :align="item1.align"
                >
                </el-table-column>
              </template>
            </template>
          </el-table-column>
        </template>
        <el-table-column min-width="1"></el-table-column>
        <template #empty>
          <el-empty :description="emptyText" :image-size="100"></el-empty>
        </template>
      </el-table>
    </div>
    <div class="lakerTable-page" v-if="!hidePagination || !hideDo">
      <div class="lakerTable-pagination">
        <el-pagination
          v-if="!hidePagination"
          :size="size"
          background
          :layout="paginationLayout"
          :total="total"
          :page-size="scPageSize"
          :page-sizes="pageSizes"
          v-model:currentPage="currentPage"
          @current-change="paginationChange"
          @update:page-size="pageSizeChange"
        ></el-pagination>
      </div>
      <div class="lakerTable-do" v-if="!hideDo">
        <el-button
          v-if="!hideAdd"
          @click="addtableitem"
          icon="el-icon-plus"
          circle
          type="primary"
          style="margin-left: 15px"
        ></el-button>
        <el-button
          v-if="!hideDelete"
          @click="deletetableitem"
          icon="el-icon-delete"
          circle
          type="danger"
          style="margin-left: 15px"
        ></el-button>
        <el-button
          v-if="canExport"
          @click="exportTableData"
          icon="sc-icon-file-excel"
          circle
          type="success"
          style="margin-left: 15px"
        ></el-button>
        <el-button
          v-if="!hideRefresh"
          @click="refresh"
          icon="el-icon-refresh"
          circle
          style="margin-left: 15px"
        ></el-button>
        <el-popover
          v-if="column"
          placement="top"
          title="列设置"
          :width="500"
          trigger="click"
          :hide-after="0"
          @show="customColumnShow = true"
          @after-leave="customColumnShow = false"
        >
          <template #reference>
            <el-button icon="el-icon-set-up" circle style="margin-left: 15px"></el-button>
          </template>
          <columnSetting
            v-if="customColumnShow"
            ref="columnSetting"
            @userChange="columnSettingChange"
            @save="columnSettingSave"
            @back="columnSettingBack"
            :column="userColumn"
          ></columnSetting>
        </el-popover>
        <el-popover v-if="!hideSetting" placement="top" title="表格设置" :width="400" trigger="click" :hide-after="0">
          <template #reference>
            <el-button icon="el-icon-setting" circle style="margin-left: 15px"></el-button>
          </template>
          <el-form label-width="80px" label-position="left">
            <el-form-item label="表格尺寸">
              <el-radio-group v-model="config.size" size="small" @change="configSizeChange">
                <el-radio-button value="large">大</el-radio-button>
                <el-radio-button value="default">正常</el-radio-button>
                <el-radio-button value="small">小</el-radio-button>
              </el-radio-group>
            </el-form-item>
            <el-form-item label="样式">
              <el-checkbox v-model="config.border" label="纵向边框"></el-checkbox>
              <el-checkbox v-model="config.stripe" label="斑马纹"></el-checkbox>
            </el-form-item>
          </el-form>
        </el-popover>
      </div>
    </div>
  </div>
</template>

<script>
import config from '@/config/table.ts'
import columnSetting from './columnSetting.vue'

export default {
  name: 'lakerTable',
  components: {
    columnSetting
  },
  props: {
    tableName: { type: String, default: '' },
    apiObj: { type: Function, default: null },
    params: { type: Object, default: () => ({}) },
    data: { type: Object, default: () => {} },
    height: { type: [String, Number], default: '100%' },
    size: { type: String, default: 'default' },
    border: { type: Boolean, default: false },
    stripe: { type: Boolean, default: false },
    pageSize: { type: Number, default: config.pageSize },
    pageSizes: { type: Array, default: config.pageSizes },
    rowKey: { type: String, default: '' },
    summaryMethod: { type: Function, default: null },
    column: { type: Object, default: () => {} },
    remoteSort: { type: Boolean, default: false },
    remoteFilter: { type: Boolean, default: false },
    remoteSummary: { type: Boolean, default: false },
    hidePagination: { type: Boolean, default: false },
    hideDo: { type: Boolean, default: false },
    hideAdd: { type: Boolean, default: true },
    hideDelete: { type: Boolean, default: true },
    hideRefresh: { type: Boolean, default: false },
    hideSetting: { type: Boolean, default: false },
    paginationLayout: { type: String, default: config.paginationLayout },
    canExport: { type: Boolean, default: false },
    exportConfig: { type: Array, default: () => [] },
    dictData: { type: Object, default: () => {} },
    defaultSort: { type: Object, default: () => {} },
    rowClassName: { type: Object, default: () => null }
  },
  watch: {
    //监听从props里拿到值了
    data() {
      this.tableData = this.data
      this.total = this.tableData.length
    },
    apiObj() {
      this.tableParams = this.params
      this.refresh()
    },
    column() {
      this.userColumn = this.column
    }
  },
  computed: {
    _height() {
      return Number(this.height) ? Number(this.height) + 'px' : this.height
    },
    _table_height() {
      return this.hidePagination && this.hideDo ? '100%' : 'calc(100% - 50px)'
    }
  },
  data() {
    return {
      scPageSize: this.pageSize,
      isActivat: true,
      emptyText: '暂无数据',
      toggleIndex: 0,
      tableData: [],
      total: 0,
      currentPage: 1,
      prop: null,
      order: null,
      loading: false,
      tableHeight: '100%',
      tableParams: this.params,
      userColumn: [],
      customColumnShow: false,
      summary: {},
      config: {
        size: this.size,
        border: this.border,
        stripe: this.stripe
      }
    }
  },
  mounted() {
    //判断是否开启自定义列
    if (this.column) {
      this.getCustomColumn()
    } else {
      this.userColumn = this.column
    }
    //判断是否静态数据
    if (this.apiObj) {
      this.getData()
    } else if (this.data) {
      this.tableData = this.data
      this.total = this.tableData.length
    }
  },
  activated() {
    if (!this.isActivat) {
      this.$refs.lakerTable.doLayout()
    }
  },
  deactivated() {
    this.isActivat = false
  },
  methods: {
    indexMethod(index) {
      return (this.currentPage - 1) * this.pageSize + index + 1
    },
    //获取列
    async getCustomColumn() {
      const userColumn = await config.columnSettingGet(this.tableName, this.column)
      this.userColumn = userColumn
    },
    formatDict(row, column, cellValue) {
      const dictList = this.dictData[column.property]
      let label = cellValue
      if (dictList) {
        dictList.forEach((element) => {
          if (element.value == cellValue) {
            label = element.label
          }
        })
      }
      return label
    },
    //获取数据
    async getData() {
      this.loading = true
      var reqData = {
        [config.request.page]: this.currentPage,
        [config.request.pageSize]: this.scPageSize
      }
      if (this.order) {
        let orderJson = [{ column: this.prop, type: this.order }]
        reqData['orderJson'] = JSON.stringify(orderJson)
      }
      if (this.defaultSort) {
        let orderJson = [{ column: this.defaultSort.prop, type: this.defaultSort.order }]
        reqData['orderJson'] = JSON.stringify(orderJson)
      }
      if (this.hidePagination) {
        delete reqData[config.request.page]
        delete reqData[config.request.pageSize]
      }
      Object.assign(reqData, this.tableParams)
      try {
        var res = await this.apiObj(reqData)
      } catch (error) {
        this.loading = false
        this.emptyText = error.statusText
        return false
      }
      try {
        var response = config.parseData(res)
      } catch (error) {
        this.loading = false
        this.emptyText = '数据格式错误'
        return false
      }
      if (response.code != config.successCode) {
        this.loading = false
        this.emptyText = response.msg
      } else {
        this.emptyText = '暂无数据'
        if (this.hidePagination) {
          this.tableData = response.data.trecords || []
        } else {
          this.tableData = response.data.records || []
          if (response.tdata) {
            this.userColumn = response.tdata
          }
        }
        this.total = response.total || 0
        this.summary = response.summary || {}
        this.loading = false
      }
      this.$refs.lakerTable.setScrollTop(0)
      this.$emit('dataChange', res, this.tableData)
    },
    //分页点击
    paginationChange() {
      this.getData()
    },
    //条数变化
    pageSizeChange(size) {
      this.scPageSize = size
      this.getData()
    },
    //刷新数据
    refresh() {
      this.$refs.lakerTable.clearSelection()
      this.getData()
    },
    addtableitem() {
      this.$nextTick(() => {
        this.$emit('addtableitem')
        //或者
      })
    },
    deletetableitem() {
      this.$nextTick(() => {
        this.$emit('deletetableitem')
        //或者
      })
    },
    formatExportData(list) {
      let index = 1
      list.forEach((item) => {
        item['index'] = index++
        for (let key in item) {
          if (item[key] === '' || item[key] == null || item[key] == undefined) {
            item[key] = ''
            item[key + '_label'] = ''
          } else {
            if (this.dictData) {
              if (this.dictData[key]) {
                this.dictData[key].forEach((element) => {
                  if (element.value === item[key]) {
                    item[key + '_label'] = element.label
                    return
                  }
                })
                if (!item[key + '_label']) {
                  item[key + '_label'] = item[key]
                }
              }
            }
          }
        }
      })
      return list
    },
    exportTableData() {
      const loading = this.$loading({
        // 打开遮罩层
        lock: true,
        text: '请稍等...',
        background: 'rgba(255, 255, 255, 0.5)'
      })
      let exportConfig = []
      if (this.userColumn && this.exportConfig.length === 0) {
        exportConfig.push({ title: '序号', key: 'index', type: 'text' })
        this.userColumn.forEach((column) => {
          if (column.children) {
            column.children.forEach((col) => {
              exportConfig.push({ title: column.label + '_' + col.label, key: col.prop, type: 'text' })
            })
          } else {
            exportConfig.push({ title: column.label, key: column.prop, type: 'text' })
          }
        })
      } else {
        //exportConfig = this.exportConfig;
        this.exportConfig.forEach((column) => {
          if (column.children) {
            column.children.forEach((col) => {
              exportConfig.push({ title: column.title + '_' + col.title, key: col.key, type: 'text' })
            })
          } else {
            exportConfig.push({ title: column.title, key: column.key, type: 'text' })
          }
        })
      }
      loading.close()
    },
    //更新数据 合并上一次params
    upData(params, page = 1) {
      this.currentPage = page
      this.$refs.lakerTable.clearSelection()
      Object.assign(this.tableParams, params || {})
      this.getData()
    },
    //重载数据 替换params
    reload(params, page = 1) {
      this.currentPage = page
      this.tableParams = params || {}
      this.$refs.lakerTable.clearSelection()
      this.$refs.lakerTable.clearSort()
      this.$refs.lakerTable.clearFilter()
      this.getData()
    },
    //自定义变化事件
    columnSettingChange(userColumn) {
      this.userColumn = userColumn
      this.toggleIndex += 1
    },
    //自定义列保存
    async columnSettingSave(userColumn) {
      this.$refs.columnSetting.isSave = true
      try {
        await config.columnSettingSave(this.tableName, userColumn)
      } catch (error) {
        this.$message.error('保存失败')
        this.$refs.columnSetting.isSave = false
      }
      this.$message.success('保存成功')
      this.$refs.columnSetting.isSave = false
    },
    //自定义列重置
    async columnSettingBack() {
      this.$refs.columnSetting.isSave = true
      try {
        const column = await config.columnSettingReset(this.tableName, this.column)
        this.userColumn = column
        this.$refs.columnSetting.usercolumn = JSON.parse(JSON.stringify(this.userColumn || []))
      } catch (error) {
        this.$message.error('重置失败')
        this.$refs.columnSetting.isSave = false
      }
      this.$refs.columnSetting.isSave = false
    },
    //排序事件
    sortChange(obj) {
      if (!this.remoteSort) {
        return false
      }
      if (obj.column && obj.prop) {
        this.prop = obj.prop
        this.order = obj.order
      } else {
        this.prop = null
        this.order = null
      }
      this.getData()
    },
    //本地过滤
    filterHandler(value, row, column) {
      const property = column.property
      return row[property] === value
    },
    //过滤事件
    filterChange(filters) {
      if (!this.remoteFilter) {
        return false
      }
      Object.keys(filters).forEach((key) => {
        filters[key] = filters[key].join(',')
      })
      this.upData(filters)
    },
    //远程合计行处理
    remoteSummaryMethod(param) {
      const { columns } = param
      const sums = []
      columns.forEach((column, index) => {
        if (index === 0) {
          sums[index] = '合'
          return
        }
        const values = this.summary[column.property]
        if (values) {
          sums[index] = values
        } else {
          sums[index] = ''
        }
      })
      return sums
    },
    configSizeChange() {
      this.$refs.lakerTable.doLayout()
    },
    //插入行 unshiftRow
    unshiftRow(row) {
      this.tableData.unshift(row)
    },
    //插入行 pushRow
    pushRow(row) {
      this.tableData.push(row)
    },
    //根据key覆盖数据
    updateKey(row, rowKey = this.rowKey) {
      this.tableData
        .filter((item) => item[rowKey] === row[rowKey])
        .forEach((item) => {
          Object.assign(item, row)
        })
    },
    //根据index覆盖数据
    updateIndex(row, index) {
      Object.assign(this.tableData[index], row)
    },
    //根据index删除
    removeIndex(index) {
      this.tableData.splice(index, 1)
    },
    //根据index批量删除
    removeIndexes(indexes = []) {
      indexes.forEach((index) => {
        this.tableData.splice(index, 1)
      })
    },
    //根据key删除
    removeKey(key, rowKey = this.rowKey) {
      this.tableData.splice(
        this.tableData.findIndex((item) => item[rowKey] === key),
        1
      )
    },
    //根据keys批量删除
    removeKeys(keys = [], rowKey = this.rowKey) {
      keys.forEach((key) => {
        this.tableData.splice(
          this.tableData.findIndex((item) => item[rowKey] === key),
          1
        )
      })
    },
    //原生方法转发
    clearSelection() {
      this.$refs.lakerTable.clearSelection()
    },
    toggleRowSelection(row, selected) {
      this.$refs.lakerTable.toggleRowSelection(row, selected)
    },
    toggleAllSelection() {
      this.$refs.lakerTable.toggleAllSelection()
    },
    toggleRowExpansion(row, expanded) {
      this.$refs.lakerTable.toggleRowExpansion(row, expanded)
    },
    setCurrentRow(row) {
      this.$refs.lakerTable.setCurrentRow(row)
    },
    clearSort() {
      this.$refs.lakerTable.clearSort()
    },
    clearFilter(columnKey) {
      this.$refs.lakerTable.clearFilter(columnKey)
    },
    doLayout() {
      this.$refs.lakerTable.doLayout()
    },
    sort(prop, order) {
      this.$refs.lakerTable.sort(prop, order)
    }
  }
}
</script>

<style scoped>
.lakerTable {
}
.lakerTable-table {
  height: calc(100% - 50px);
}
.lakerTable-page {
  height: 50px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 15px;
}
.lakerTable-do {
  white-space: nowrap;
}
.lakerTable:deep(.el-table__footer) .cell {
  font-weight: bold;
}
.lakerTable:deep(.el-table__body-wrapper) .el-scrollbar__bar.is-horizontal {
  height: 12px;
  border-radius: 12px;
}
.lakerTable:deep(.el-table__body-wrapper) .el-scrollbar__bar.is-vertical {
  width: 12px;
  border-radius: 12px;
}
.lakerTable:deep(.el-table) {
  --el-table-header-bg-color: var(--el-fill-color);
}
</style>
